Lesson 6: Memory Leaks
By: Darkwulfv, edited by wyrmlord


What is a memory leak?
-A memory leak is caused by bad coding, where a handle that was stored in memory is lost from refrence. Basically, it’s something that got placed in wc3’s memory usage and never got removed, and is unable to be removed.

What does a memory leak do?
-A memory leak adds a little tiny bit of memory usage to Wc3 when it’s running. If enough memory leaks, your map is going to cause some serious lag.

What causes memory leaks?
-When a handle is created, it's stored it in Wc3’s memory. If it is not destroyed or removed when you are done with it, then it stays there, taking up memory.

Well how am I supposed to fix them?
-Well, there are a few ways to do so, depending.


function MemoryLeak takes nothing returns nothing
call AddSpecialEffect() //Creates a special effect
endfunction


The native AddSpecialEffect(…) creates an effect. If you do not destroy this effect with the proper function, it will stay embedded in the memory, and thus take up memory. Now, one leak is terribly insignificant. But if your map made a lot of leaks very often, you would notice a big change.

Here’s a way to fix that leak:

function MemoryLeak takes nothing returns nothing
local effect my_effect = AddSpecialEffect(...) //Create a special effect
call DestroyEffect(my_effect) //Destroys the effect, removing it from memory
set my_effect = null //You have to null local handles at the end of a function, or they leak too
endfunction

//Alternatively, this can be used

function MemoryLeak2 takes nothing
call DestroyEffect(AddSpecialEffect(...))
//Adds a special effect and destroys it all at once. This will still show the animation once for most (not necessarily all) effects, and doesn't require the use of a variable
//However, if you want to see the entire animation, you should wait for the duration of the effect's 'stand' animation
endfunction


This method goes for anytime you are using a handle(any variable that isn’t a real, integer, boolean, code, or string)
However, the destroying/removing function changes for each type of handle. A list of variable types and how to remove them will be given later for you to refer to.

NOTE: When destroying/removing an object, you are removing/destroying a specific object and not the variable itself. The variable just points to the location in memory where the object is stored.


NOTE: A leak can be defined as an object that is created, not removed, unable to be removed during the game (assuming not removing it is undesired). If it’s only used once (like dummy units, rects, groups, etc.) then remove it. If not, you should leave it. (Like for spells, don’t remove the caster!)
NOTE: All non-handle variables except strings do not leak. String leaks cannot be fixed, but you usually don't need to worry about them.

So memory leaks only apply when you create things?
-WRONG!
A memory leak not only happens when you create things. It also happens when you make a handle-variable, set it to a value, and don’t null it.
Example:


function MemoryLeak takes nothing returns nothing
local unit u
//actions
endfunction


This example wouldn't leak, as the handle variable wasn't set to a value. However, if it had been set to a value, like:

local unit u = GetTriggerUnit()

It would leak. To fix this, set your variable to null. (Reals, integers, and booleans cannot be nulled, and don't need to be as the memory they use is automatically removed)
To null a variable, simply put

set yourvariable = null

You don't need to set a variable to null after removing each object. You only need to null it once; this is usually done at the end of a function.


function MemoryLeak takes nothing returns nothing
local group g = CreateGroup()

//Some code

set g = null
endfunction


NOTE: To satisfy those wanting to know why handle variables leak (not referring to the object, I'm referring to the variable). When you set a handle equal to a value, the handle points to where that value is stored in memory. It will remain pointing to where that value is stored unless it is set to null (meaning 0, not pointing to a specific place in memory.)

What about globals?
-Since these are always in the memory to begin with, and are always available, they don't count as leaks (and don't need to be nulled).

So uh… What do I do about non-handle variables?
-They don’t leak though, so worry not.

Conclusion:
-Always clean leaks. If you don’t, and there’s enough leaks, you will notice the effects.

Challenge!
-Clean this function of all memory leaks:

function ChallengeTrigger takes nothing returns nothing
local unit u = GetTriggerUnit() //This unit is in the game, it needs to be kept (hint)
local effect SFX = AddSpecialEffect()
local group g = CreateGroup()
local unit u2 //this is going to be a dummy unit and should be removed (hint)
local real r = 4
//actions
//(hint) only one of these variables isn’t nulled.
endfunction


Good luck!